use std::{borrow::Cow, sync::Arc};

use reedline::Prompt;

/// 监视器颜色提示符
pub type MonColor = reedline::Color;

static DEFAULT_MULTILINE_INDICATOR: &str = "::: ";

/// 监视器提示器
pub trait ReadlinePrompt {
    /// 提供左侧内容的完整提示字符
    fn render_prompt_left(&self) -> Cow<str>;
    /// 提供右侧内容的完整提示字符
    fn render_prompt_right(&self) -> Cow<str>;
    /// 提供指示器字符
    fn render_prompt_indicator(&self) -> Cow<str>;
    /// 提供左侧提示符颜色
    fn get_prompt_left_color(&self) -> MonColor {
        MonColor::Green
    }
    /// 提供右侧提示符颜色
    fn get_prompt_right_color(&self) -> MonColor {
        MonColor::AnsiValue(5)
    }
    /// 提供指示器字符颜色
    fn get_indicator_color(&self) -> MonColor {
        MonColor::Cyan
    }
}

/// 监视器提示符
pub struct MonitorPrompt {
    prompt: Arc<dyn ReadlinePrompt>,
}

#[allow(unsafe_code)]
unsafe impl Send for MonitorPrompt {}
#[allow(unsafe_code)]
unsafe impl Sync for MonitorPrompt {}

impl MonitorPrompt {
    /// 创建监视器提示符
    pub fn new(prompt: Arc<dyn ReadlinePrompt>) -> Self {
        Self { prompt }
    }
}

impl Prompt for MonitorPrompt {
    fn get_indicator_color(&self) -> MonColor {
        self.prompt.get_indicator_color()
    }

    fn get_prompt_color(&self) -> MonColor {
        self.prompt.get_prompt_left_color()
    }

    fn get_prompt_right_color(&self) -> MonColor {
        self.prompt.get_prompt_right_color()
    }

    fn render_prompt_history_search_indicator(
        &self,
        history_search: reedline::PromptHistorySearch,
    ) -> Cow<str> {
        let prefix = match history_search.status {
            reedline::PromptHistorySearchStatus::Passing => "",
            reedline::PromptHistorySearchStatus::Failing => "failing ",
        };

        std::borrow::Cow::Owned(format!("({}reverse-search: {}) ", prefix, history_search.term))
    }

    fn render_prompt_indicator(&self, _: reedline::PromptEditMode) -> Cow<str> {
        self.prompt.render_prompt_indicator()
    }

    fn render_prompt_left(&self) -> Cow<str> {
        self.prompt.render_prompt_left()
    }

    fn render_prompt_multiline_indicator(&self) -> Cow<str> {
        std::borrow::Cow::Borrowed(DEFAULT_MULTILINE_INDICATOR)
    }

    fn render_prompt_right(&self) -> Cow<str> {
        self.prompt.render_prompt_right()
    }
}

/// 默认的监视器提示符
pub struct DefaultMonitorPrompt {
    prompt: String,
    indicator: String,
}

impl DefaultMonitorPrompt {
    /// 构建默认的监视器提示符
    pub fn new(prompt: &str, indicator: &str) -> Self {
        Self { prompt: prompt.into(), indicator: indicator.into() }
    }
}

impl ReadlinePrompt for DefaultMonitorPrompt {
    /// 提供左侧简单的提示符
    fn render_prompt_left(&self) -> Cow<str> {
        Cow::Borrowed(&self.prompt)
    }
    /// 提供右侧内容的完整提示字符
    fn render_prompt_right(&self) -> Cow<str> {
        Cow::Owned("".into())
    }
    /// 提供指示器字符
    fn render_prompt_indicator(&self) -> Cow<str> {
        Cow::Borrowed(&self.indicator)
    }
}
